pacman::p_load(readxl, gifski, gapminder,
plotly, gganimate, tidyverse)Hands-on Exercise 3.2: Programming Animated Statistical Graphics with R
1 Overview
Animated graphics can capture the audience’s attention and leave a lasting impression, making them highly effective for visually-driven data storytelling. In this hands-on exercise, you will learn to create animated data visualizations using the gganimate and plotly R packages. Additionally, you’ll explore how to:
Reshape data with the tidyr package.
Process, wrangle, and transform data using the dplyr package.
1.1 Basic concepts of animation
Animations in data visualization work by sequentially displaying individual plots, which are then stitched together to create a movie-like effect, much like a flipbook or traditional cartoon. Each frame represents a different subset of the data, driving the perceived motion when combined.

1.2 Terminology
Before creating animated visualizations, it’s essential to understand the following concepts:
Frame: Each frame represents a specific time point or category. As the frame changes, the graph updates to reflect new data.
Animation Attributes: These settings control the animation’s behavior, such as frame duration, transition easing functions, and starting points (current frame vs. beginning).
Tip: Consider whether an animated graphic adds value to your analysis. For exploratory data analysis, animations might not justify the effort. However, in presentations, well-placed animations can significantly enhance engagement and comprehension.
2 Getting Started
2.1 Loading the R packages
The code chunk below checks if the below packages are installed and load them into your working R environment.
plotly: For creating interactive statistical graphs.
gganimate: A ggplot2 extension for creating animations.
gifski: Converts video frames into high-quality GIFs using efficient color palette techniques.
gapminder: Includes Gapminder data, particularly for country color schemes.
tidyverse: A suite of R packages for data science, including tools for creating static statistical graphs.
2.2 Importing the data
In this exercise, we’ll use the Data worksheet from the GlobalPopulation Excel workbook. The below code chunk imports this data into R environment using appropriate package from tidyverse family.
col <- c("Country", "Continent")
globalPop <- read_xls("data/GlobalPopulation.xls",
sheet="Data") %>%
mutate_each_(funs(factor(.)), col) %>%
mutate(Year = as.integer(Year))Key learnings from the abobe code chunk:
read_xls()from the readxl package is used to import Excel worksheets.mutate_each_()from dplyr converts all character data types to factors.mutate()from dplyr converts the values in theYearcolumn to integers for proper handling in plots.
Unfortunately, mutate_each_() was deprecated in dplyr 0.7.0. and funs() was deprecated in dplyr 0.8.0. In view of this, we will re-write the code using mutate_at() as shown in the code chunk below.
col <- c("Country", "Continent")
globalPop <- read_xls("data/GlobalPopulation.xls",
sheet="Data") %>%
mutate_at(col, as.factor) %>%
mutate(Year = as.integer(Year))Instead of using mutate_at(), across() can be used to derive the same outputs.
col <- c("Country", "Continent")
globalPop <- read_xls("data/GlobalPopulation.xls",
sheet="Data") %>%
mutate(across(col, as.factor)) %>%
mutate(Year = as.integer(Year))3 Animated Data Visualisation: gganimate methods
gganimate enhances the grammar of graphics in ggplot2 by introducing grammar classes specifically for animation. These classes allow you to customize how a plot evolves over time, enabling dynamic storytelling.
Key grammar classes include:
transition_*(): Specifies how data should be distributed and connected across time.view_*(): Controls how positional scales adjust throughout the animation.shadow_*(): Determines how data from other time points is displayed at a given moment.enter_*()/exit_*(): Manages the appearance of new data and the disappearance of old data during the animation.ease_aes(): Dictates the easing behavior for various aesthetics during transitions.
3.1 Building a static population bubble plot
The code chunk below uses the basic ggplot2 functions to create a static bubble plot.
ggplot(globalPop, aes(x = Old, y = Young,
size = Population,
colour = Country)) +
geom_point(alpha = 0.7,
show.legend = FALSE) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
labs(title = 'Year: {frame_time}',
x = '% Aged',
y = '% Young') 
3.2 Building the animated bubble plot
The following code chunk demonstrates key animation techniques:
transition_time(): A function from gganimate that creates transitions across distinct time states, such asYear.ease_aes(): Controls the easing of aesthetics during transitions. By default, easing is linear, but other methods include quadratic, cubic, quartic, quintic, sine, circular, exponential, elastic, back, and bounce, allowing for smoother or more dynamic effects.
ggplot(globalPop, aes(x = Old, y = Young,
size = Population,
colour = Country)) +
geom_point(alpha = 0.7,
show.legend = FALSE) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
labs(title = 'Year: {frame_time}',
x = '% Aged',
y = '% Young') +
transition_time(Year) +
ease_aes('linear') 
4 Animated Data Visualisation: plotly
In the Plotly R package, both ggplotly() and plot_ly() enable keyframe animations using the frame argument or aesthetic. Additionally, they support the ids argument or aesthetic, which ensures smooth transitions between objects sharing the same ID, thereby enhancing object constancy during animations.
4.1 Building an animated bubble plot: ggplotly() method
In this sub-section, we explore how to create an animated bubble plot using ggplotly() method.
The animated bubble plot above includes a play/pause button and a slider to control the animation
gg <- ggplot(globalPop,
aes(x = Old,
y = Young,
size = Population,
colour = Country)) +
geom_point(aes(size = Population,
frame = Year),
alpha = 0.7,
show.legend = FALSE) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
labs(x = '% Aged',
y = '% Young')
ggplotly(gg)Key takeaways from the code chunk above:
Static Bubble Plot Creation: The code employs appropriate ggplot2 functions to construct a static bubble plot, which is stored as an R object named
gg.Animation Conversion: The
ggplotly()function is used to transform the static R graphic object into an animated SVG object, enabling interactivity and animation.
Notice that although show.legend = FALSE argument was used, the legend still appears on the plot. To overcome this problem, theme(legend.position='none') should be used as shown in the below plot and code chunk.
gg <- ggplot(globalPop,
aes(x = Old,
y = Young,
size = Population,
colour = Country)) +
geom_point(aes(size = Population,
frame = Year),
alpha = 0.7) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
labs(x = '% Aged',
y = '% Young') +
theme(legend.position='none')
ggplotly(gg)4.2 Building an animated bubble plot: plot_ly() method
In this sub-section, we explore how to create an animated bubble plot using plot_ly() method.
bp <- globalPop %>%
plot_ly(x = ~Old,
y = ~Young,
size = ~Population,
color = ~Continent,
sizes = c(2, 100),
frame = ~Year,
text = ~Country,
hoverinfo = "text",
type = 'scatter',
mode = 'markers'
) %>%
layout(showlegend = FALSE)
bp